<template>
	<view class="uni-indexed-list" ref="list" id="list">
		<!-- #ifdef APP-NVUE -->
		<list class="uni-indexed-list__scroll" scrollable="true" show-scrollbar="false">
			<cell v-for="(list, idx) in lists" :key="idx" :ref="'uni-indexed-list-' + idx">
				<!-- #endif -->
				<!-- #ifndef APP-NVUE -->
				<scroll-view :scroll-into-view="scrollViewId" class="uni-indexed-list__scroll" scroll-y>
					<view v-for="(list, idx) in lists" :key="idx" :id="'uni-indexed-list-' + idx">
						<!-- #endif -->
						<indexed-list-item :list="list" :loaded="loaded" :idx="idx" :showSelect="showSelect"
							@itemClick="onClick"></indexed-list-item>
						<!-- #ifndef APP-NVUE -->
					</view>
				</scroll-view>
				<!-- #endif -->
				<!-- #ifdef APP-NVUE -->
			</cell>
		</list>
		<!-- #endif -->
		<view class="uni-indexed-list__menu" @touchstart="touchStart" @touchmove.stop.prevent="touchMove"
			@touchend="touchEnd" @mousedown.stop="mousedown" @mousemove.stop.prevent="mousemove"
			@mouseleave.stop="mouseleave">
			<view v-for="(list, key) in lists" :key="key" class="uni-indexed-list__menu-item"
				:class="touchmoveIndex == key ? 'uni-indexed-list__menu--active' : ''">
				<text class="uni-indexed-list__menu-text"
					:class="touchmoveIndex == key ? 'uni-indexed-list__menu-text--active' : ''">{{ list.key }}</text>
			</view>
		</view>
		<view v-if="touchmove" class="uni-indexed-list__alert-wrapper">
			<text class="uni-indexed-list__alert">{{ lists[touchmoveIndex].key }}</text>
		</view>
	</view>
</template>
<script>
import indexedListItem from './uni-indexed-list-item.vue'
// #ifdef APP-NVUE
const dom = weex.requireModule('dom')
// #endif
// #ifdef APP-PLUS
function throttle (func, delay) {
  let prev = Date.now()
  return function () {
    const context = this
    const args = arguments
    const now = Date.now()
    if (now - prev >= delay) {
      func.apply(context, args)
      prev = Date.now()
    }
  }
}

function touchMove (e) {
  const pageY = e.touches[0].pageY
  const index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
  if (this.touchmoveIndex === index) {
    return false
  }
  const item = this.lists[index]
  if (item) {
    // #ifndef APP-NVUE
    this.scrollViewId = 'uni-indexed-list-' + index
    this.touchmoveIndex = index
    // #endif
    // #ifdef APP-NVUE
    dom.scrollToElement(this.$refs['uni-indexed-list-' + index][0], {
      animated: false
    })
    this.touchmoveIndex = index
    // #endif
  }
}
const throttleTouchMove = throttle(touchMove, 40)
// #endif

/**
	 * IndexedList 索引列表
	 * @description 用于展示索引列表
	 * @tutorial https://ext.dcloud.net.cn/plugin?id=375
	 * @property {Boolean} showSelect = [true|false] 展示模式
	 * 	@value true 展示模式
	 * 	@value false 选择模式
	 * @property {Object} options 索引列表需要的数据对象
	 * @event {Function} click 点击列表事件 ，返回当前选择项的事件对象
	 * @example <uni-indexed-list options="" showSelect="false" @click=""></uni-indexed-list>
	 */
export default {
  name: 'UniIndexedList',
  components: {
    indexedListItem
  },
  emits: ['click'],
  props: {
    options: {
      type: Array,
      default () {
        return []
      }
    },
    showSelect: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      lists: [],
      winHeight: 0,
      itemHeight: 0,
      winOffsetY: 0,
      touchmove: false,
      touchmoveIndex: -1,
      scrollViewId: '',
      touchmovable: true,
      loaded: false,
      isPC: false
    }
  },
  watch: {
    options: {
      handler: function () {
        this.setList()
      },
      deep: true
    }
  },
  mounted () {
    // #ifdef H5
    this.isPC = this.IsPC()
    // #endif
    setTimeout(() => {
      this.setList()
    }, 50)
    setTimeout(() => {
      this.loaded = true
    }, 300)
  },
  methods: {
    setList () {
      const index = 0
      this.lists = []
      this.options.forEach((value, index) => {
        if (value.data.length === 0) {
          return
        }
        const indexBefore = index
        const items = value.data.map(item => {
          const obj = {}
          obj.key = value.letter
          obj.name = item
          obj.itemIndex = index
          index++
          obj.checked = item.checked ? item.checked : false
          return obj
        })
        this.lists.push({
          title: value.letter,
          key: value.letter,
          items,
          itemIndex: indexBefore
        })
      })
      // #ifndef APP-NVUE
      uni.createSelectorQuery()
        .in(this)
        .select('#list')
        .boundingClientRect()
        .exec(ret => {
          this.winOffsetY = ret[0].top
          this.winHeight = ret[0].height
          this.itemHeight = this.winHeight / this.lists.length
        })
      // #endif
      // #ifdef APP-NVUE
      dom.getComponentRect(this.$refs.list, (res) => {
        this.winOffsetY = res.size.top
        this.winHeight = res.size.height
        this.itemHeight = this.winHeight / this.lists.length
      })
      // #endif
    },
    touchStart (e) {
      this.touchmove = true
      const pageY = this.isPC ? e.pageY : e.touches[0].pageY
      const index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
      const item = this.lists[index]
      if (item) {
        this.scrollViewId = 'uni-indexed-list-' + index
        this.touchmoveIndex = index
        // #ifdef APP-NVUE
        dom.scrollToElement(this.$refs['uni-indexed-list-' + index][0], {
          animated: false
        })
        // #endif
      }
    },
    touchMove (e) {
      // #ifndef APP-PLUS
      const pageY = this.isPC ? e.pageY : e.touches[0].pageY
      const index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
      if (this.touchmoveIndex === index) {
        return false
      }
      const item = this.lists[index]
      if (item) {
        this.scrollViewId = 'uni-indexed-list-' + index
        this.touchmoveIndex = index
      }
      // #endif
      // #ifdef APP-PLUS
      throttleTouchMove.call(this, e)
      // #endif
    },
    touchEnd () {
      this.touchmove = false
      // this.touchmoveIndex = -1
    },

    /**
			 * 兼容 PC @tian
			 */

    mousedown (e) {
      if (!this.isPC) return
      this.touchStart(e)
    },
    mousemove (e) {
      if (!this.isPC) return
      this.touchMove(e)
    },
    mouseleave (e) {
      if (!this.isPC) return
      this.touchEnd(e)
    },

    // #ifdef H5
    IsPC () {
      const userAgentInfo = navigator.userAgent
      const Agents = ['Android', 'iPhone', 'SymbianOS', 'Windows Phone', 'iPad', 'iPod']
      let flag = true
      for (let v = 0; v < Agents.length - 1; v++) {
        if (userAgentInfo.indexOf(Agents[v]) > 0) {
          flag = false
          break
        }
      }
      return flag
    },
    // #endif

    onClick (e) {
      const {
        idx,
        index
      } = e
      const obj = {}
      for (const key in this.lists[idx].items[index]) {
        obj[key] = this.lists[idx].items[index][key]
      }
      const select = []
      if (this.showSelect) {
        this.lists[idx].items[index].checked = !this.lists[idx].items[index].checked
        this.lists.forEach((value, idx) => {
          value.items.forEach((item, index) => {
            if (item.checked) {
              const obj = {}
              for (const key in this.lists[idx].items[index]) {
                obj[key] = this.lists[idx].items[index][key]
              }
              select.push(obj)
            }
          })
        })
      }
      this.$emit('click', {
        item: obj,
        select
      })
    }
  }
}
</script>
<style lang="scss" scoped>
	.uni-indexed-list {
		position: absolute;
		left: 0;
		top: 0;
		right: 0;
		bottom: 0;
		/* #ifndef APP-NVUE */
		display: flex;
		/* #endif */
		flex-direction: row;
	}

	.uni-indexed-list__scroll {
		flex: 1;
	}

	.uni-indexed-list__menu {
		width: 24px;
		/* #ifndef APP-NVUE */
		display: flex;
		/* #endif */
		flex-direction: column;
	}

	.uni-indexed-list__menu-item {
		/* #ifndef APP-NVUE */
		display: flex;
		/* #endif */
		flex: 1;
		align-items: center;
		justify-content: center;
		/* #ifdef H5 */
		cursor: pointer;
		/* #endif */
	}

	.uni-indexed-list__menu-text {
		font-size: 12px;
		text-align: center;
		color: #aaa;
	}

	.uni-indexed-list__menu--active {
		// background-color: rgb(200, 200, 200);
	}

	.uni-indexed-list__menu--active {}

	.uni-indexed-list__menu-text--active {
		border-radius: 16px;
		width: 16px;
		height: 16px;
		line-height: 16px;
		background-color: #007aff;
		color: #fff;
	}

	.uni-indexed-list__alert-wrapper {
		position: absolute;
		left: 0;
		top: 0;
		right: 0;
		bottom: 0;
		/* #ifndef APP-NVUE */
		display: flex;
		/* #endif */
		flex-direction: row;
		align-items: center;
		justify-content: center;
	}

	.uni-indexed-list__alert {
		width: 80px;
		height: 80px;
		border-radius: 80px;
		text-align: center;
		line-height: 80px;
		font-size: 35px;
		color: #fff;
		background-color: rgba(0, 0, 0, 0.5);
	}
</style>
